#define CORE_IS_BAD			//	While core images are bad, conduct analyses with display images only.

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using ObjectLib;

namespace ObjectParser
{
	/// <summary>
	/// Summary description for FormLightMap.
	/// </summary>
	public class FormLightMap : System.Windows.Forms.Form
	{
		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			this.Pb = new ObjectParser.PbViewer();
			this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
			this.but1 = new ObjectParser.SpecialButton();
			this.but2 = new ObjectParser.SpecialButton();
			this.but3 = new ObjectParser.SpecialButton();
			this.but4 = new ObjectParser.SpecialButton();
			this.but5 = new ObjectParser.SpecialButton();
			this.but6 = new ObjectParser.SpecialButton();
			this.but7 = new ObjectParser.SpecialButton();
			this.but8 = new ObjectParser.SpecialButton();
			this.but9 = new ObjectParser.SpecialButton();
			this.mainMenu1 = new System.Windows.Forms.MainMenu();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.mCopyZoomed = new System.Windows.Forms.MenuItem();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.mNodeColor = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.mPixVals = new System.Windows.Forms.MenuItem();
			this.statusBar1 = new System.Windows.Forms.StatusBar();
			this.trackBar1 = new System.Windows.Forms.TrackBar();
			this.label1 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
			this.SuspendLayout();
			// 
			// Pb
			// 
			this.Pb.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right)));
			this.Pb.Location = new System.Drawing.Point(0, 0);
			this.Pb.Name = "Pb";
			this.Pb.Size = new System.Drawing.Size(288, 240);
			this.Pb.TabIndex = 0;
			this.Pb.TabStop = false;
			// 
			// but1
			// 
			this.but1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but1.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but1.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but1.Location = new System.Drawing.Point(320, 0);
			this.but1.Name = "but1";
			this.but1.Size = new System.Drawing.Size(40, 23);
			this.but1.TabIndex = 0;
			this.but1.TabStop = false;
			this.but1.Tag = "1";
			this.but1.Text = "1";
			this.toolTip1.SetToolTip(this.but1, "Darkest");
			// 
			// but2
			// 
			this.but2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but2.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but2.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but2.Location = new System.Drawing.Point(320, 24);
			this.but2.Name = "but2";
			this.but2.Size = new System.Drawing.Size(40, 23);
			this.but2.TabIndex = 0;
			this.but2.TabStop = false;
			this.but2.Tag = "2";
			this.but2.Text = "2";
			this.toolTip1.SetToolTip(this.but2, "Very Dark");
			// 
			// but3
			// 
			this.but3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but3.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but3.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but3.Location = new System.Drawing.Point(320, 48);
			this.but3.Name = "but3";
			this.but3.Size = new System.Drawing.Size(40, 23);
			this.but3.TabIndex = 0;
			this.but3.TabStop = false;
			this.but3.Tag = "3";
			this.but3.Text = "3";
			this.toolTip1.SetToolTip(this.but3, "Dark");
			// 
			// but4
			// 
			this.but4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but4.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but4.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but4.Location = new System.Drawing.Point(320, 72);
			this.but4.Name = "but4";
			this.but4.Size = new System.Drawing.Size(40, 23);
			this.but4.TabIndex = 0;
			this.but4.TabStop = false;
			this.but4.Tag = "4";
			this.but4.Text = "4";
			this.toolTip1.SetToolTip(this.but4, "Barely Dark");
			// 
			// but5
			// 
			this.but5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but5.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but5.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but5.Location = new System.Drawing.Point(320, 104);
			this.but5.Name = "but5";
			this.but5.Size = new System.Drawing.Size(40, 23);
			this.but5.TabIndex = 0;
			this.but5.TabStop = false;
			this.but5.Tag = "5";
			this.but5.Text = "5";
			this.toolTip1.SetToolTip(this.but5, "Natural");
			// 
			// but6
			// 
			this.but6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but6.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but6.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but6.Location = new System.Drawing.Point(320, 136);
			this.but6.Name = "but6";
			this.but6.Size = new System.Drawing.Size(40, 23);
			this.but6.TabIndex = 0;
			this.but6.TabStop = false;
			this.but6.Tag = "6";
			this.but6.Text = "6";
			this.toolTip1.SetToolTip(this.but6, "Barely Specularized");
			// 
			// but7
			// 
			this.but7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but7.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but7.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but7.Location = new System.Drawing.Point(320, 160);
			this.but7.Name = "but7";
			this.but7.Size = new System.Drawing.Size(40, 23);
			this.but7.TabIndex = 0;
			this.but7.TabStop = false;
			this.but7.Tag = "7";
			this.but7.Text = "7";
			this.toolTip1.SetToolTip(this.but7, "Specularized");
			// 
			// but8
			// 
			this.but8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but8.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but8.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but8.Location = new System.Drawing.Point(320, 184);
			this.but8.Name = "but8";
			this.but8.Size = new System.Drawing.Size(40, 23);
			this.but8.TabIndex = 0;
			this.but8.TabStop = false;
			this.but8.Tag = "8";
			this.but8.Text = "8";
			this.toolTip1.SetToolTip(this.but8, "Very Specularized");
			// 
			// but9
			// 
			this.but9.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.but9.Cursor = System.Windows.Forms.Cursors.Cross;
			this.but9.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
			this.but9.Location = new System.Drawing.Point(320, 208);
			this.but9.Name = "but9";
			this.but9.Size = new System.Drawing.Size(40, 23);
			this.but9.TabIndex = 0;
			this.but9.TabStop = false;
			this.but9.Tag = "9";
			this.but9.Text = "9";
			this.toolTip1.SetToolTip(this.but9, "Most Specularized");
			// 
			// mainMenu1
			// 
			this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem2,
																					  this.menuItem1,
																					  this.menuItem3});
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 0;
			this.menuItem2.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.mCopyZoomed});
			this.menuItem2.Text = "Edit";
			// 
			// mCopyZoomed
			// 
			this.mCopyZoomed.Index = 0;
			this.mCopyZoomed.Text = "Copy Zoomed Region";
			this.mCopyZoomed.Click += new System.EventHandler(this.mCopyZoomed_Click);
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 1;
			this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.mNodeColor});
			this.menuItem1.Text = "Options";
			// 
			// mNodeColor
			// 
			this.mNodeColor.Index = 0;
			this.mNodeColor.Text = "Set Light Node Color...";
			this.mNodeColor.Click += new System.EventHandler(this.mNodeColor_Click);
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 2;
			this.menuItem3.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.mPixVals});
			this.menuItem3.Text = "Output";
			// 
			// mPixVals
			// 
			this.mPixVals.Index = 0;
			this.mPixVals.Text = "Pixel Values";
			this.mPixVals.Click += new System.EventHandler(this.mPixVals_Click);
			// 
			// statusBar1
			// 
			this.statusBar1.Location = new System.Drawing.Point(0, 233);
			this.statusBar1.Name = "statusBar1";
			this.statusBar1.Size = new System.Drawing.Size(368, 24);
			this.statusBar1.TabIndex = 1;
			this.statusBar1.Text = "Ready.";
			// 
			// trackBar1
			// 
			this.trackBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Right)));
			this.trackBar1.Location = new System.Drawing.Point(288, 24);
			this.trackBar1.Name = "trackBar1";
			this.trackBar1.Orientation = System.Windows.Forms.Orientation.Vertical;
			this.trackBar1.Size = new System.Drawing.Size(45, 192);
			this.trackBar1.TabIndex = 2;
			this.trackBar1.TickStyle = System.Windows.Forms.TickStyle.TopLeft;
			// 
			// label1
			// 
			this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
			this.label1.Location = new System.Drawing.Point(288, 216);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(48, 23);
			this.label1.TabIndex = 3;
			this.label1.Text = "Hard";
			// 
			// label2
			// 
			this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
			this.label2.Location = new System.Drawing.Point(288, 0);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(40, 23);
			this.label2.TabIndex = 4;
			this.label2.Text = "Soft";
			this.label2.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
			// 
			// FormLightMap
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(368, 257);
			this.Controls.Add(this.statusBar1);
			this.Controls.Add(this.but9);
			this.Controls.Add(this.but8);
			this.Controls.Add(this.but7);
			this.Controls.Add(this.but6);
			this.Controls.Add(this.but5);
			this.Controls.Add(this.but4);
			this.Controls.Add(this.but3);
			this.Controls.Add(this.but2);
			this.Controls.Add(this.but1);
			this.Controls.Add(this.Pb);
			this.Controls.Add(this.label2);
			this.Controls.Add(this.label1);
			this.Controls.Add(this.trackBar1);
			this.Menu = this.mainMenu1;
			this.Name = "FormLightMap";
			this.Text = "Light Map";
			this.toolTip1.SetToolTip(this, "Create a light map for an object.");
			((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
			this.ResumeLayout(false);

		}
		#endregion
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.ToolTip toolTip1;
		private System.Windows.Forms.MainMenu mainMenu1;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem mNodeColor;

		public static Font LightnessFont;
		public static Color LightNodeColor;
		public static Pen LightNodePenInactive;
		public static Pen LightNodePenActive;
		private ObjectParser.SpecialButton but1;
		private ObjectParser.SpecialButton but2;
		private ObjectParser.SpecialButton but3;
		private ObjectParser.SpecialButton but4;
		private ObjectParser.SpecialButton but5;
		private ObjectParser.SpecialButton but6;
		private ObjectParser.SpecialButton but7;
		private ObjectParser.SpecialButton but8;
		private ObjectParser.SpecialButton but9;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem mCopyZoomed;
		private System.Windows.Forms.StatusBar statusBar1;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem mPixVals;
		private System.Windows.Forms.TrackBar trackBar1;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		public static SolidBrush LightNodeBrushValue;
		static FormLightMap()
		{
			SetLightNodeColor(Color.Blue);
			LightnessFont = new Font("Arial", 8, FontStyle.Regular);
		}
		public static void SetLightNodeColor(Color col)
		{
			LightNodeColor = col;
			LightNodePenActive = new Pen(col, 1.0f);
			LightNodeBrushValue = new SolidBrush(col);
			LightNodePenInactive = new Pen(col,1.0f);
			LightNodePenInactive.DashStyle = DashStyle.Dot;
		}

		public FormParse FormParse;
		public ObjectParserData Opd { get { return FormParse.Opd; } }
		public ParsedObject ActiveObject{ get { return FormParse.Opd.ActiveObject; } }

		public ObjectParser.PbViewer Pb;
		public SpecialButton[] Buttons;
		
		public FormLightMap(FormParse FormParse)
		{
			InitializeComponent();

			//	Initialize the buttons.
			InitButtons();
			//	Initialize the LightMapTool
			LmTool = new LightMapTool(this);
			//	The PbViewer doesn't capture the mouse-wheel event, so help it out.
			this.MouseWheel += new MouseEventHandler(Pb.PbViewer_MouseWheel);
			//	Initialize the bitmap.
			Pb.Init(FormParse.Bmp);
			//	Initialize the paint-over event handler.
			Pb.Paint += new PaintEventHandler(Pb_Paint);
			//	Link us to the FormParse window.
			this.FormParse = FormParse;
			//	View the active object.
			Pb.InitZoom(ActiveObject.BoundingRect);
			//	Initialize some toggle variables.
			DrawGrayScale=DrawNodes=RefreshLightMaps=true;
		}
		public void InitButtons()
		{
			Buttons = new SpecialButton[] {but1, but2, but3, but4, but5, but6, but7, but8, but9};
			float incr = 255.0f/(float)Buttons.Length;
			for(int i=0; i<Buttons.Length; i++)
			{
				Buttons[i].Tag = i+1;
				Buttons[i].BackColor = LightMap.Gray[(int)(incr*(float)i)];
				if(i==4)
					Buttons[i].ForeColor = Color.Blue;
				else
					Buttons[i].ForeColor = LightMap.Gray[(int)(incr*(float)(8-i))];
				Buttons[i].Click += new EventHandler(butAddNode_Click);
				Buttons[i].Invalidate();
				Buttons[i].FormLm = this;
			}
		}
		public readonly float DefaultSd = 25.0f;
		/// <summary>
		/// True when the gray-scale bitmaps of the light map is to be drawn on Pb.
		/// </summary>
		public bool DrawGrayScale;
		/// <summary>
		/// True when the nodes of the light map are to be drawn on Pb.
		/// </summary>
		public bool DrawNodes;
		/// <summary>
		/// Set to true in order to invalidate the Bitmap LightMapCache in the pixel taggers of a ParsedObject.
		/// This must be done when a pixel tagger changes or when the light map changes.
		/// </summary>
		public bool RefreshLightMaps;
		/// <summary>
		/// The tool which responds to mouse events and changes the light-map as a result.
		/// </summary>
		public LightMapTool LmTool;
		/// <summary>
		/// Draws a single light node.
		/// </summary>
		/// <param name="node">LightNode  The node to be drawn.</param>
		/// <param name="g">Graphics  The graphics object for Pb.  If null, the object is created and then destroyed on exit of this function.</param>
		/// <param name="isActive">bool  If true, drawn as the active node.  If false, drawn as inactive.</param>
		/// <param name="pbNodeSquare">RectangleF  The square that defines the node's circular contour.</param>
		public void DrawLightNode(LightNode node, Graphics g, bool isActive, RectangleF pbNodeSquare)
		{
			//	Create the graphics object if necessary
			if(g==null)
				g = Pb.CreateGraphics();
			//	Draw the circle.
			if(isActive)
				g.DrawEllipse( LightNodePenActive, pbNodeSquare );
			else
				g.DrawEllipse( LightNodePenInactive, pbNodeSquare );
			//	Draw the light value.
			Point pt = new Point((int)pbNodeSquare.Location.X-5, (int)pbNodeSquare.Location.Y-5);
			g.DrawString(Convert.ToString((int)(node.Lightness*4.0f+5.5f)), LightnessFont, LightNodeBrushValue, pt);
		}
		/// <summary>
		/// Gives the square that defines the node's circular contour.
		/// </summary>
		/// <param name="node"></param>
		/// <returns></returns>
		public RectangleF GetPbNodeSquare(LightNode node)
		{
			//	First, compute the factor by which we are zoomed in (>1) or zoomed out (<1).
			RectangleF rf = Pb.ImgRect;
			float zoomFactor = (float)Pb.Width/(float)rf.Width;
			//	Second, determine the radius of our circle in Pb coordinates.  Make it 2 sd out.
			float radius = ((float)node.Sd)*zoomFactor;
			//	Third, determine the control coordinates.
			PointF center = Pb.ImgToViewer( node.Location );
			//	Fourth, compute the square.
			return new RectangleF(center.X-radius, center.Y-radius, 2.0f*radius, 2.0f*radius);
		}
		/// <summary>
		/// Draws the light map onto the Pb surface.
		/// </summary>
		/// <param name="map">LightMap  The map of nodes to be drawn.</param>
		/// <param name="g">Graphics  The graphics object for Pb.  If null, the object is created and then destroyed on exit of this function.</param>
		public void DrawLightMap(LightMap map, Graphics g)
		{
			int i;
			//	Create the graphics object if necessary
			if(g==null)
				g = Pb.CreateGraphics();
			//	Draw the gray-scale (if necessary)
			if(DrawGrayScale)
			{
				RectangleF destRect;
				PixelTagger pix;
				//	Each polygon has its own gray-scale bitmap
				for(i=0; i<ActiveObject.Polygons.Count; i++)
				{
					pix = ActiveObject.Polygons[i].Pix;
					//	Refresh the bitmap if necessary.
					if(RefreshLightMaps)
						map.PaintLight(pix, pix.TaggedRect, pix.LightMapCache);
					//	Get the destination rect
					destRect = Pb.ImgToViewerRectF(pix.TaggedRectF);
					//	Draw the grayscale bitmap
					g.DrawImage(pix.LightMapCache, destRect);
				}
				//	Since the updates have occurred (if necessary), make sure this variable is false.
				RefreshLightMaps=false;
			}
			//	Draw each light-node (if necessary)
			if(DrawNodes)
			{
				for(i=0; i<map.Count; i++)
					DrawLightNode(map[i], g, map[i]==LmTool.ActiveNode, GetPbNodeSquare(map[i]));
			}
		}

		/// <summary>
		/// Set the light node color.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void mNodeColor_Click(object sender, System.EventArgs e)
		{		
		}

		private void butAddNode_Click(object sender, System.EventArgs e)
		{
			LightNode node = new LightNode( ( (float)(int)(((SpecialButton)sender).Tag)-5.0f)/4.0f,
				DefaultSd, DefaultSd, Pb.ViewerToImg(Pb.PointToClient(Cursor.Position)), 2.0);
			LmTool.EnterAddMode(node);
			Pb.Focus();
		}
		public void Pb_Paint(object sender, PaintEventArgs e)
		{
			DrawLightMap(ActiveObject.LightMap, e.Graphics);
		}
		public void Pb_MouseLeave(object sender, MouseEventArgs e)
		{
			Cursor = Cursors.Default;
		}
		/// <summary>
		/// Copy the contents of the window to the clipboard.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		public void mCopyZoomed_Click(object sender, System.EventArgs e)
		{
			Bitmap bmp = new Bitmap(Pb.Width, Pb.Height);
			Graphics g = Graphics.FromImage(bmp);
			PaintEventArgs p = new PaintEventArgs(g, new Rectangle(0,0,Pb.Width,Pb.Height));
			Pb.PbViewer_Paint(this, p);
			Pb_Paint(this, p);
			Clipboard.SetDataObject(bmp);
		}
		protected override void OnKeyDown(KeyEventArgs e)
		{
			LmTool.FormLm_KeyDown(this, e);
		}
		protected override void OnKeyUp(KeyEventArgs e)
		{
			LmTool.FormLm_KeyUp(this, e);
		}
		protected override void OnKeyPress(KeyPressEventArgs e)
		{
		}
		public void Public_OnKeyDown(KeyEventArgs e)
		{
			OnKeyDown(e);
		}
		public void Public_OnKeyUp(KeyEventArgs e)
		{
			OnKeyUp(e);
		}
		public void Public_OnKeyPress(KeyPressEventArgs e)
		{
			OnKeyPress(e);
		}

		private void mPixVals_Click(object sender, System.EventArgs e)
		{
			Cursor.Current = Cursors.WaitCursor;
			ParsedObject actObj = this.ActiveObject;
			if(actObj != null)
			{
#if CORE_IS_BAD
				string imgName = FormParse.Opd.DisplayImagename;
				if(imgName==null || imgName.Length==0)
					imgName=FormParse.Opd.Imagename;
#else
				string imgName = FormParse.Opd.Imagename;
#endif
				Bitmap bmp = UnsafeSupport.OpenBitmap(imgName);
				statusBar1.Text = "Checking for color map cache.";
				//	Check for an existing cache.
				ColorMapCache cache = ColorMapCache.GetCache( imgName );
				ColorMap colorMap=null;;
				if(cache == null)	//	Cache the new values
				{
					statusBar1.Text = "Generating new color map cache.";
					colorMap = new ColorMap( imgName , bmp);
				}
				else	//	Use the cached values
				{
					statusBar1.Text = "Found color map cache.";
					colorMap = new ColorMap( cache, bmp);
				}

				int ct=0,i,j;
				int totalPix = 0;
				for(i=0; i<actObj.Polygons.Count; i++)
					totalPix += actObj.Polygons[i].Pix.NumPts;
				string totalPixStr = Convert.ToString(totalPix);

				FileStream txtFile = new FileStream("C:\\Documents and Settings\\ing\\Desktop\\output.txt", FileMode.Create);
				StreamWriter sw = new StreamWriter(txtFile);

				//sw.WriteLine("LconeLog\tMconeLog\tSconeLog\tRg\tBy\tHue\tSat\tLum\tLightVal");
				

				ColorValues values = new ColorValues();
				for(int p=0; p<actObj.Polygons.Count; p++)
				{
					PolygonF pf = actObj.Polygons[p];
					Rectangle bound = pf.Pix.TaggedRect;
					for(i=bound.Left; i<=bound.Right; i++)
						for(j=bound.Top; j<=bound.Bottom; j++)
						{
							if(pf.Pix.PixelIsTagged(i,j))
							{
								colorMap.CalcValues(i,j,values);
								sw.WriteLine(
									Convert.ToString(values.LconeLog) + '\t' + 
									Convert.ToString(values.MconeLog) + '\t' + 
									Convert.ToString(values.SconeLog) + '\t' + 
									Convert.ToString(values.Rg) + '\t' + 
									Convert.ToString(values.By) + '\t' + 
									Convert.ToString(values.Hue) + '\t' + 
									Convert.ToString(values.Sat) + '\t' + 
									Convert.ToString(values.Lum) + '\t' + 
									Convert.ToString(actObj.LightMap.LightValue(i,j)) );
								statusBar1.Text = Convert.ToString(ct) + "  /  " + totalPixStr;
							}
						}
				}
				sw.Close();
			}
			Cursor.Current = Cursors.Default;
			statusBar1.Text = "Ready.";
		}
	}
	public enum LmToolStatus { Adding, Moving, Deleting, Default };
	public class LightMapTool : IDisposable
	{
		public FormLightMap FormLm;
		public LmToolStatus Status;
		public LightNode AddNode, MoveNode;
		public LightNode ActiveNode;
		public RectangleF LastPbNodeSquare;
		public PointF MoveNodeInitialLocation;
		public Cursor OldCursor;
		public bool CtrlKeyIsDown=false, ShiftKeyIsDown=false;
		public ParsedObject ActiveObject;
		public LightNode Copied;

		public LightMapTool(FormLightMap FormLm)
		{
			this.FormLm = FormLm;
			Status = LmToolStatus.Default;

			FormLm.Pb.MouseDown += new MouseEventHandler(this.Pb_MouseDown);
			FormLm.Pb.MouseUp += new MouseEventHandler(this.Pb_MouseUp);
			FormLm.Pb.MouseEnter += new EventHandler(this.Pb_MouseEnter);
			FormLm.Pb.MouseLeave += new EventHandler(this.Pb_MouseLeave);
			FormLm.Pb.MouseMove += new MouseEventHandler(this.Pb_MouseMove);
			FormLm.Pb.KeyDown = new KeyEventHandler(this.FormLm_KeyDown);
			FormLm.Pb.KeyUp = new KeyEventHandler(this.FormLm_KeyUp);

			FormLm.MouseWheel += new MouseEventHandler(this.Pb_MouseWheel);
			FormLm.KeyDown += new KeyEventHandler(this.FormLm_KeyDown);
			FormLm.KeyUp += new KeyEventHandler(this.FormLm_KeyUp);
			
			for(int i=0; i<FormLm.Buttons.Length; i++)
			{
				FormLm.Buttons[i].KeyDown += new KeyEventHandler(this.FormLm_KeyDown);
				FormLm.Buttons[i].KeyUp += new KeyEventHandler(this.FormLm_KeyUp);
			}
		}
		public void Dispose()
		{
			if(FormLm!=null)
			{
				if(FormLm.Pb!=null)
				{
					FormLm.Pb.MouseDown -= new MouseEventHandler(this.Pb_MouseDown);
					FormLm.Pb.MouseUp -= new MouseEventHandler(this.Pb_MouseUp);
					FormLm.Pb.MouseEnter -= new EventHandler(this.Pb_MouseEnter);
					FormLm.Pb.MouseLeave -= new EventHandler(this.Pb_MouseLeave);
					FormLm.Pb.MouseMove -= new MouseEventHandler(this.Pb_MouseMove);
					FormLm.Pb.KeyDown = null;
					FormLm.Pb.KeyUp = null;
				}
				FormLm.MouseWheel -= new MouseEventHandler(this.Pb_MouseWheel);
				FormLm.KeyDown -= new KeyEventHandler(this.FormLm_KeyDown);
				FormLm.KeyUp -= new KeyEventHandler(this.FormLm_KeyUp);
				for(int i=0; i<FormLm.Buttons.Length; i++)
				{
					FormLm.Buttons[i].KeyDown -= new KeyEventHandler(this.FormLm_KeyDown);
					FormLm.Buttons[i].KeyUp -= new KeyEventHandler(this.FormLm_KeyUp);
				}
			}
		}
		public void EnterAddMode(LightNode AddNode)
		{
			Status = LmToolStatus.Adding;
			this.AddNode = this.ActiveNode = AddNode;
			FormLm.ActiveObject.LightMap.Add(AddNode);
			LastPbNodeSquare = FormLm.GetPbNodeSquare(ActiveNode);
			ActiveObject = FormLm.ActiveObject;
		}
		/// <summary>
		/// Finds the active node based on the current cursor position.
		/// Invalidates if the active node has changed position or identity.
		/// </summary>
		public void FindActiveNode()
		{
			//	Remember an old value in case invalidation is required.
			RectangleF lastPbSq = LastPbNodeSquare;
			//	Get the new active object and node.
			ActiveObject = FormLm.ActiveObject;
			ActiveNode = ActiveObject.LightMap.GetNearestNode( FormLm.Pb.ViewerToImg(FormLm.Pb.PointToClient(Cursor.Position)) );
			//	Invalidation if necessary.
			if(ActiveNode==null)
			{
				if(LastPbNodeSquare.Width!=0)
					FormLm.Pb.Invalidate(LastPbNodeSquare, 3.0f);
			}
			else
			{
				//	Get the new active node's invalidation square.
				LastPbNodeSquare = FormLm.GetPbNodeSquare(ActiveNode);
				//	Invalidate if necessary.
				if( LastPbNodeSquare != lastPbSq )
				{
					FormLm.Pb.Invalidate(LastPbNodeSquare, 3.0f);
					FormLm.Pb.Invalidate(lastPbSq, 3.0f);
				}
			}
		}
		/// <summary>
		/// Called when the mouse enters the Pb window.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		public void Pb_MouseEnter(object sender, EventArgs e)
		{
			OldCursor = Cursor.Current;
			Cursor.Current = Cursors.Cross;
		}
		/// <summary>
		/// Called when the mouse enters the Pb window.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		public void Pb_MouseLeave(object sender, EventArgs e)
		{
			Cursor.Current = OldCursor;
		}
		public void Pb_MouseMove(object sender, MouseEventArgs e)
		{
			//	Invalidate for adding or moving a node.
			if(Status==LmToolStatus.Adding || Status==LmToolStatus.Moving)
			{
				FormLm.Pb.Invalidate(LastPbNodeSquare, 3.0f);
				ActiveNode.Location = FormLm.Pb.ViewerToImg(FormLm.Pb.PointToClient(Cursor.Position));
				LastPbNodeSquare = FormLm.GetPbNodeSquare(ActiveNode);
				FormLm.Pb.Invalidate(LastPbNodeSquare, 3.0f);
			}
			else if(Status==LmToolStatus.Default)
				FindActiveNode();
		}
		public void Pb_MouseWheel(object sender, MouseEventArgs e)
		{
			if(ActiveNode!=null)
			{
				if(CtrlKeyIsDown && ShiftKeyIsDown)	//	Sharpen or soften the light node
				{
					if( (   e.Delta<0.0 && ActiveNode.Sharpness > 1.0 )
						|| e.Delta>=0.0 )
					{
						if(e.Delta>0)
							ActiveNode.Sharpness *= 1.1f;
						else
							ActiveNode.Sharpness *= 0.9f;
						FormLm.RefreshLightMaps=true;
						FormLm.Pb.Invalidate();
					}
				}
				else if(CtrlKeyIsDown)	//	Change the and volume and sd of the curve
				{
					if( (   e.Delta<0.0 && ActiveNode.Sd > 0.01 )
						|| e.Delta>=0.0 )
					{
						if(e.Delta>0)
						{
							ActiveNode.Sd *= 1.1f;
							ActiveNode.Volume *= 1.1f;
						}
						else
						{
							ActiveNode.Sd *= 0.9f;
							ActiveNode.Volume *= 0.9f;
						}
						FormLm.RefreshLightMaps=true;
						FormLm.Pb.Invalidate();
					}
				}
				else if(ShiftKeyIsDown)	//	Raise the area under the curve.
				{
					if(e.Delta>0)
						ActiveNode.Volume *= 1.1f;
					else
						ActiveNode.Volume *= 0.9f;
					FormLm.RefreshLightMaps=true;
					FormLm.Pb.Invalidate();
				}
			}
		}
		public void Pb_MouseDown(object sender, MouseEventArgs e)
		{
		}
		public void Pb_MouseUp(object sender, MouseEventArgs e)
		{
			//	Finish add
			if(Status==LmToolStatus.Adding && e.Button==MouseButtons.Left)
			{
				//	TO DO:  Add the active node.
				//	TO DO:  Encode the addition as an Undo macro and put it on the stack.
				FormLm.RefreshLightMaps=true;
				Status = LmToolStatus.Default;
				FormLm.Pb.Invalidate();
			}
			//	Finish move
			else if(Status==LmToolStatus.Moving && e.Button==MouseButtons.Left)
			{
				//	TO DO:  Move the active node.
				//	TO DO:  Encode the move as an Undo macro and put it on the stack.
				FormLm.RefreshLightMaps=true;
				Status = LmToolStatus.Default;
				FormLm.Pb.Invalidate();
			}
			//	Delete
			else if(Status==LmToolStatus.Default && e.Button==MouseButtons.Left && ActiveNode != null && CtrlKeyIsDown)
			{
				ActiveObject.LightMap.Remove(ActiveNode);
				//	TO DO:  Encode the deletion as an Undo macro and put it on the stack.
				FormLm.RefreshLightMaps=true;
				Status = LmToolStatus.Default;
				FormLm.Pb.Invalidate();
			}
			//	Start Move
			else if(Status==LmToolStatus.Default && e.Button==MouseButtons.Left && ActiveNode != null)
			{
				Status = LmToolStatus.Moving;
				this.MoveNodeInitialLocation = ActiveNode.Location;
				this.MoveNode = ActiveNode;
			}
		}
		public void FormLm_KeyUp(object sender, KeyEventArgs e)
		{
			CtrlKeyIsDown = e.Control;
			ShiftKeyIsDown= e.Shift;
			//	Constrain the zooming and panning ability of the FormLm.Pb control.
			FormLm.Pb.Zoom = FormLm.Pb.Pan = !e.Control && !e.Shift;
			//	Break out of active mode or move mode.
			if(e.KeyCode == Keys.Escape)
			{
				//	Break out of add mode by deleting the active node from the light map.
				if(Status == LmToolStatus.Adding)
					ActiveObject.LightMap.Remove(ActiveNode);
					//	Break out of move mode by restoring the point's original location.
				else if(Status == LmToolStatus.Moving)
					ActiveNode.Location = this.MoveNodeInitialLocation;
				//	Return to default mode and set node markers to null.
				Status = LmToolStatus.Default;
				AddNode=MoveNode=null;
				//	Find a new active node.
				FindActiveNode();				//	This will invalidate appropriately.
			}
				//	Copy the window to the clipboard
			else if(e.KeyCode == Keys.C && e.Control)
			{
				if(ActiveNode != null)
					FormLm.mCopyZoomed_Click(this,null);
			}
				//	Toggle gray map
			else if(e.KeyCode == Keys.Space)
			{
				FormLm.DrawGrayScale = !FormLm.DrawGrayScale;
				FormLm.Pb.Invalidate();
			}
				//	Toggle blue
			else if(e.KeyCode == Keys.B)
			{
				FormLm.DrawNodes = !FormLm.DrawNodes;
				FormLm.Pb.Invalidate();
			}
				//	Copy the active light-node.
			else if(e.KeyCode == Keys.C)
			{
				if(ActiveNode != null && Status==LmToolStatus.Default)
					Copied = ActiveNode.Clone;
			}
				//	Paste the copied light node.
			else if(e.KeyCode == Keys.V)
			{
				if(Copied != null && Status==LmToolStatus.Default)
					EnterAddMode(Copied.Clone);
			}
			//	Sharpen quiclky
			else if(e.KeyCode == Keys.Up && e.Control)
			{
				FormLm.ActiveObject.LightMap.Sharpen(5.0);
				FormLm.RefreshLightMaps=true;
				FormLm.Pb.Invalidate();
			}
			//	Sharpen slowly
			else if(e.KeyCode == Keys.Up && e.Shift)
			{
				FormLm.ActiveObject.LightMap.Sharpen(1.2);
				FormLm.RefreshLightMaps=true;
				FormLm.Pb.Invalidate();
			}
			//	Sharpen
			else if(e.KeyCode == Keys.Up)
			{
				FormLm.ActiveObject.LightMap.Sharpen(2.0);
				FormLm.RefreshLightMaps=true;
				FormLm.Pb.Invalidate();
			}
			//	Soften quiclky
			else if(e.KeyCode == Keys.Down && e.Control)
			{
				FormLm.ActiveObject.LightMap.Sharpen(0.2);
				FormLm.RefreshLightMaps=true;
				FormLm.Pb.Invalidate();
			}
			//	Soften slowly
			else if(e.KeyCode == Keys.Down && e.Shift)
			{
				FormLm.ActiveObject.LightMap.Sharpen(0.9);
				FormLm.RefreshLightMaps=true;
				FormLm.Pb.Invalidate();
			}
			//	Soften
			else if(e.KeyCode == Keys.Down)
			{
				FormLm.ActiveObject.LightMap.Sharpen(0.5);
				FormLm.RefreshLightMaps=true;
				FormLm.Pb.Invalidate();
			}
		}
		public void FormLm_KeyDown(object sender, KeyEventArgs e)
		{
			CtrlKeyIsDown = e.Control;
			ShiftKeyIsDown= e.Shift;
			//	Constrain the zooming and panning ability of the FormLm.Pb control.
			FormLm.Pb.Zoom = FormLm.Pb.Pan = !e.Control && !e.Shift;
		}
	}
}
